package com.zm.rpc.procedure;

import java.lang.reflect.Method;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import com.zm.rpc.procedure.anno.Procedure;
import com.zm.rpc.procedure.anno.RpcService;
import com.zm.rpc.procedure.pojo.ProcedureMetadata;

@Component
public class ProcedureInitializer implements BeanPostProcessor{

    @Autowired
    private ApplicationContext ctx;

    @Override
    @Nullable
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   
        RpcService annoRpcService = bean.getClass().getDeclaredAnnotation(RpcService.class);
        if(annoRpcService != null){
            this.doProcedureInit(bean, annoRpcService);
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

    private void doProcedureInit(Object bean,RpcService annoRpcService){
       

        Method[] methods = bean.getClass().getDeclaredMethods();

        for(Method m : methods){
             Procedure annoProcedure =m.getDeclaredAnnotation(Procedure.class);
             if(annoProcedure != null){
                this.doProcedureRegistor(bean, annoRpcService, m, annoProcedure);
             }
        }

       
    }

    private void doProcedureRegistor(Object bean,RpcService annoRpcService,Method targetMethod, Procedure annoProcedure){
        ProcedureCenter pc = this.ctx.getBean(ProcedureCenter.class);
        ProcedureMetadata metadata = new ProcedureMetadata();
        metadata.setPath(annoRpcService.value() + "/"+ annoProcedure.value());
        metadata.setProcedure(bean);
        metadata.setTargetMethod(targetMethod);
        pc.register(metadata);
    }
    
}
